package com.zhupanlin.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;


/**
 * 描述信息：
 *
 * @author zhupanlin
 * @version 1.0
 * @date 2024/12/24 10:19
 */
/*@Configuration
@EnableAuthorizationServer*/
public class JdbcAuthorizationSeverConfig extends AuthorizationServerConfigurerAdapter {

    private final DataSource dataSource;
    private final PasswordEncoder passwordEncoder;
    private final AuthenticationManager authenticationManager;


//    @Autowired
    public JdbcAuthorizationSeverConfig(DataSource dataSource, PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager) {
        this.dataSource = dataSource;
        this.passwordEncoder = passwordEncoder;
        this.authenticationManager = authenticationManager;
    }

    @Bean
    public ClientDetailsService clientDetails() {
        JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
        jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
        return jdbcClientDetailsService;
    }

    /**
     * 配置客户端
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());
    }

    /**
     * 配置令牌存储
     * @return
     */
//    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 认证管理器
        endpoints.authenticationManager(authenticationManager);
        endpoints.tokenStore(tokenStore());

        // 修改默认令牌生成服务
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        // 基于数据库令牌生成
        tokenServices.setTokenStore(endpoints.getTokenStore());
        // 是否支持刷新令牌
        tokenServices.setSupportRefreshToken(true);
        // 是否重复使用刷新令牌(直到过期)
        tokenServices.setReuseRefreshToken(true);

        // 设置客户端信息
        tokenServices.setClientDetailsService(clientDetails());
        // 用来控制令牌存储增强策略
        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
        // 访问令牌的默认有效期(以秒为单位)。过期的令牌为零或负数 30天
        tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));
        // 刷新令牌的有效性(以秒为单位)。如果小于等于零，则不会过期
        tokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(3));
        // 使用配置令牌服务
        endpoints.tokenServices(tokenServices);

    }
}
